package com.lwq.imserver.service;

import com.lwq.imserver.model.ChatMessage;
import com.lwq.imserver.model.FriendsApply;
import com.lwq.imserver.model.SendBody;
import com.lwq.imserver.model.TransferModel;
import com.lwq.imserver.model.system.SysUser;
import com.lwq.imserver.util.MongoUtil;
import com.lwq.imserver.util.StringUtils;
import com.lwq.imserver.util.WebSocketUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Description:
 * Author: LiuWenQing
 * Datetime: 2022/1/27 16:52
 */
@Service
public class UserService {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private PasswordEncoder pe;
    @Autowired
    private MongoUtil<SysUser> userMongoUtil;
    @Autowired
    private MongoUtil<FriendsApply> applyMongoUtil;

    public void add(SysUser user) {
        SysUser model = mongoTemplate.findOne(Query.query(Criteria.where("name").is(user.getName())), SysUser.class);
        if (model != null) throw new RuntimeException("账号已存在");
        user.setCreateDate(new Date());
        user.setPassword(pe.encode(user.getPassword()));
        mongoTemplate.insert(user);
        WebSocketUtil.userList = mongoTemplate.findAll(SysUser.class);
    }

    @Transactional(rollbackFor = Exception.class)
    public void changeAvatar(String userId, String avatar) {
        SysUser user = mongoTemplate.findById(userId, SysUser.class);
        if (user == null) throw new RuntimeException("系统异常");
        mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(userId)), Update.update("avatar" , avatar), SysUser.class);
        mongoTemplate.updateMulti(Query.query(Criteria.where("from").is(userId)), Update.update("fromAvatar" , avatar), ChatMessage.class);
        WebSocketUtil.userList = mongoTemplate.findAll(SysUser.class);
    }

    public List<SysUser> userList(Boolean isOn, String userId, Boolean isAddFriends) {
        Criteria criteria = new Criteria();
        if (StringUtils.isNotEmpty(userId)) {
            criteria.and("friends.id").ne(userId);
            if (isAddFriends) {
                List<FriendsApply> friendsApplyList = mongoTemplate.find(Query.query(Criteria.where("from.id").is(userId)), FriendsApply.class);
                // mongo一个字段不能加多个查询条件
                if (friendsApplyList.isEmpty()) {
                    criteria.and("id").ne(userId);
                } else {
                    Set<String> tempIds = friendsApplyList.stream().map(e -> e.getTo().getId()).collect(Collectors.toSet());
                    tempIds.add(userId);
                    criteria.and("id").nin(tempIds);
                }
            }
        }
        List<SysUser> userList = mongoTemplate.find(Query.query(criteria).with(Sort.by(Sort.Order.desc("lastLoginDate"))), SysUser.class);
        if (Objects.nonNull(isOn) && isOn == true) {
            userList.forEach(e -> {
                e.setIsOnline(WebSocketUtil.getChannelMap().containsKey(e.getId()));
            });
        }
        return userList;
    }

    public Map<String, Object> noReadCount(String userId) {
        long count = mongoTemplate.count(Query.query(Criteria.where("to.id").is(userId).and("isRead").is(false)), FriendsApply.class);
        Map<String,Object> reMap = new HashMap<>();
        reMap.put("noReadApplyCount",count);
        return reMap;
    }

    @Transactional(rollbackFor = Exception.class)
    public void addFriend(FriendsApply friendsApply) {
        friendsApply.setIsRead(false);
        friendsApply.setIsAgree(false);
        friendsApply.setTimestamp(Calendar.getInstance().getTimeInMillis());
        friendsApply = mongoTemplate.insert(friendsApply);
        SendBody sendBody = new SendBody();
        sendBody.setReceive(friendsApply.getTo().getId());
        sendBody.setApply(friendsApply);
        sendBody.setType(TransferModel.APPLY_FRIEND);
        WebSocketUtil.singleCast(sendBody);
    }

    @Transactional(rollbackFor = Exception.class)
    public void confirmApply(String id) {
        FriendsApply friendsApply = mongoTemplate.findById(id, FriendsApply.class);
        if (friendsApply == null) throw new RuntimeException("系统异常");
        friendsApply.setIsAgree(true);
        friendsApply.setIsRead(true);
        applyMongoUtil.update(friendsApply, friendsApply.getId());
        SysUser user = mongoTemplate.findById(friendsApply.getFrom().getId(), SysUser.class);
        if (user == null) throw new RuntimeException("系统异常");
        List<SysUser> friends = user.getFriends();
        if (!friends.isEmpty()) {
            friends.add(friendsApply.getTo());
            user.setFriends(friends);
        } else {
            List<SysUser> tempList = new ArrayList<>();
            tempList.add(friendsApply.getTo());
            user.setFriends(tempList);
        }
        userMongoUtil.update(user, user.getId());
    }
}
